package com.yuantu.judiciary.security.handler;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.yuantu.judiciary.common.SysOnOffState;
import com.yuantu.judiciary.dao.IOrganizationDao;
import com.yuantu.judiciary.dao.IOrganizationSourceDao;
import com.yuantu.judiciary.model.domain.OrganizationDO;
import com.yuantu.judiciary.model.enums.AuthState;
import com.yuantu.judiciary.model.enums.OrganizationType;
import com.yuantu.judiciary.model.vo.EntListVO;
import com.yuantu.judiciary.model.vo.OrganizationNameSimpleVO;
import com.yuantu.judiciary.model.vo.PageVO;
import com.yuantu.judiciary.service.ICheckEnterpriseService;
import com.yuantu.judiciary.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;


@Slf4j
public class OrganizationInfoListener implements ReadListener<OrganizationNameSimpleVO> {

    /**
     * 每隔5条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 1000;
    /**
     * 缓存的数据
     */
    private List<OrganizationNameSimpleVO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private Long organizationSourceId;

    private IOrganizationDao organizationDao;

    private IOrganizationSourceDao organizationSourceDao;

    private ICheckEnterpriseService enterpriseService;


    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * 由于示例没有进行数据库操作，这里传了一个文件名作为额外参数示例，传DAO方法雷同
     */
//    public OrganizationInfoListener(String fileName) {
//        this.fileName = fileName;
//    }
    public OrganizationInfoListener(IOrganizationDao organizationDao, IOrganizationSourceDao organizationSourceDao,
                                    ICheckEnterpriseService enterpriseService, Long organizationSourceId) {
        this.organizationDao = organizationDao;
        this.organizationSourceDao = organizationSourceDao;
        this.enterpriseService = enterpriseService;
        this.organizationSourceId = organizationSourceId;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(OrganizationNameSimpleVO data, AnalysisContext context) {
//        log.info("解析到一条数据:{}", JSONUtil.toJsonStr(data));

        // TODO 如果需要对数据设置额外参数，可以在此处处理,比如创建人、创建时间等等
        cachedDataList.add(data);

        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", cachedDataList.size());
        //todo 执行保存逻辑
        Pageable pageable = PageRequest.of(0, 10);
        for (OrganizationNameSimpleVO organizationNameSimple : cachedDataList) {
            String name = organizationNameSimple.getName();
            PageVO<EntListVO> enterprisePageInfo = enterpriseService.getEnterpriseList(name, pageable);
            List<EntListVO> enterInfos = enterprisePageInfo.getData();
            Optional<EntListVO> first = Optional.ofNullable(enterInfos)
                    .map(Collection::stream)
                    .orElseGet(Stream::empty)
                    .filter(s -> name != null && name.equals(s.getEnterpriseName()))
                    .findFirst();
            if (first.isPresent()) {
                EntListVO entList = first.get();
                if (!StringUtil.isEmpty(entList.getCreditCode())) {
                    OrganizationDO organization = organizationDao.findInfoByCreditCodeAndDeletedFalse(entList.getCreditCode());
                    if (organization == null) {
                        organization = new OrganizationDO();
                        organization.setEnterName(name);
                        organization.setType(OrganizationType.ENTER);
                        organization.setAuthState(AuthState.PASS);
                        organization.setState(SysOnOffState.ON);
                        organization.setCreditCode(entList.getCreditCode());
                        organization.setOrganizationSourceId(organizationSourceId);
                    } else {
                        Long existOrganizationSourceId = organization.getOrganizationSourceId();
                        if (existOrganizationSourceId == null) {
                            organization.setOrganizationSourceId(organizationSourceId);
                        }
                    }
                    organizationDao.save(organization);
                    MyLogoutHandler myLogoutHandler = new MyLogoutHandler();
                    myLogoutHandler.hashCode();

                }
            }
        }

        log.info("存储数据库成功！");
    }


}
